package com.start.dataSource.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.start.common.exceptions.StartBusException;
import com.start.common.tools.DataTableTools;
import com.start.dataSource.entity.StartGenTableColumn;
import com.start.dataSource.entity.StartSourceDataTable;
import com.start.dataSource.entity.StartTableColumn;
import com.start.dataSource.mappers.StartDataTableMapper;
import com.start.dataSource.service.StartDataTableService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class StartDataTableServiceImpl implements StartDataTableService {
    @Autowired
    private StartDataTableMapper startDataTableMapper;
    @Autowired
    private DynamicRoutingDataSource dynamicRoutingDataSource;

    @DS("#dataSourcesKey")
    @Override
    public Page<StartSourceDataTable> pageSystemTable(Page page, Wrapper<StartSourceDataTable> wrapper, String dataSourcesKey) {
        return startDataTableMapper.pageSystemTable(page, wrapper);
    }

    @Override
    public void updateById(StartSourceDataTable entity) {
        startDataTableMapper.updateById(entity);
    }


    @Override
    public StartSourceDataTable getTableById(String id, boolean isLoadOption) {
        StartSourceDataTable table = startDataTableMapper.selectById(id);
        if (table == null) {
            return null;
        }
        if (!isLoadOption) {
            return table;
        }
        if (table.getCrudOption() == null || table.getCrudOption().isEmpty()) {
            List<StartGenTableColumn> columns = startDataTableMapper.queryByTableColumn(table.getDataSourceKeyFlag(), table.getTableName());
            JSONObject option = new JSONObject();
            JSONArray columnArray = new JSONArray();
            for (StartGenTableColumn column : columns) {
                JSONObject col = new JSONObject();
                col.put("label", column.getColumnComment());
                col.put("type", "input");
                col.put("prop", com.baomidou.mybatisplus.core.toolkit.StringUtils.underlineToCamel(column.getColumnName()));
                columnArray.add(col);
            }
            option.put("column", columnArray);
            table.setCrudOption(option);
        }
        return table;
    }

    @Override
    public StartSourceDataTable getTableByTableName(String dataSourceKeyFlag, String tableName, boolean isLoadOption) {
        if (dbHasTable(dataSourceKeyFlag, tableName)) {
            throw new StartBusException("请先同步数据表");
        }
        LambdaQueryWrapper<StartSourceDataTable> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StartSourceDataTable::getDataSourceKeyFlag, dataSourceKeyFlag);
        lambdaQueryWrapper.eq(StartSourceDataTable::getTableName, tableName);
        final StartSourceDataTable startSourceDataTable = startDataTableMapper.selectOne(lambdaQueryWrapper);
        if (startSourceDataTable == null) return null;
        return startSourceDataTable;
    }

    @Override
    public boolean dbHasTable(String dataSourceKeyFlag, String tableName) {
        return startDataTableMapper.getTableCount(dataSourceKeyFlag, tableName) > 0;
    }


    @Override
    public void removeTableById(String id) {
        StartSourceDataTable table = getTableById(id, false);
        if (table == null) {
            return;
        }
        startDataTableMapper.deleteById(table.getId());
        deleteTable(table.getDataSourceKeyFlag(), table.getTableName());
    }


    @DS("#dataSourcesKey")
    public void deleteTable(String dataSourcesKey, String tableName) {
        Integer tableCount = startDataTableMapper.getTableCount(dataSourcesKey, tableName);
        if (tableCount == null || tableCount < 1) {
            return;
        }
        startDataTableMapper.deleteTable(tableName);
    }


    @Override
    public void save(StartSourceDataTable entity) {
        startDataTableMapper.insert(entity);
    }

    @Override
    public void synchronizationTable(String dataSourcesKey, String tableName) {
        StartSourceDataTable table = getTableById(dataSourcesKey, true);
        if (table == null) {
            throw new StartBusException("数据表：" + tableName + "不存在请检查该数据表是否被删除！");
        }
        if (table.getCrudOption() == null || table.getCrudOption().isEmpty()) {
            throw new StartBusException("请先设计数据表");
        }
        Integer tableCount = startDataTableMapper.getTableCount(dataSourcesKey, tableName);
        JSONObject crudOption = table.getCrudOption();
        if (tableCount < 1) {
            String sql = DataTableTools.avueOptionToColumnSQL(crudOption);
            startDataTableMapper.createTable(dataSourcesKey, sql);
            return;
        }
        Map<String, StartGenTableColumn> startGenTableColumns = startDataTableMapper.queryByTableColumn(dataSourcesKey, tableName).stream().collect(Collectors.toMap(StartTableColumn::getColumnName, e -> e, (e1, e2) -> e1));

        List<String> addColumns = new ArrayList<>();
        JSONArray columns = crudOption.getJSONArray("column");
        Map<String, JSONObject> newColumnName = new LinkedHashMap<>();
        for (int i = 0; i < columns.size(); i++) {
            JSONObject column = columns.getJSONObject(i);
            String prop = column.getString("prop");
            String columnName = com.baomidou.mybatisplus.core.toolkit.StringUtils.underlineToCamel(prop);
            newColumnName.put(columnName, column);
            StartGenTableColumn oldColumn = startGenTableColumns.getOrDefault(columnName, null);
            if (oldColumn == null) {
                addColumns.add(columnName);
            }
        }
        Set<String> oldColumnNames = startGenTableColumns.keySet();
        List<String> deleteColumns = new ArrayList<>();
        for (String oldColumnName : oldColumnNames) {
            if (!newColumnName.containsKey(oldColumnName)) {
                deleteColumns.add(oldColumnName);
            }
        }


    }

    @Override
    public boolean hasDataSource(String dataSourcesKey) {
        return !dynamicRoutingDataSource.getDataSources().containsKey(dataSourcesKey);
    }

    @Override
    public void createTable(StartSourceDataTable entity) {
        if (StringUtils.isBlank(entity.getTableName())) {
            throw new StartBusException("数据表名称不能为空");
        }
        if (StringUtils.isBlank(entity.getDataSourceKeyFlag())) {
            throw new StartBusException("请选择数据源");
        }
        final JSONObject crudOption = entity.getCrudOption();
        if (crudOption == null || crudOption.isEmpty()) {
            JSONObject option = new JSONObject();
            JSONArray column = new JSONArray();

        }

    }

    @Override
    public JSONObject getDesignConfig(String dataSourcesKey, String tableName) {
        LambdaQueryWrapper<StartSourceDataTable> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StartSourceDataTable::getDataSourceKeyFlag, dataSourcesKey);
        lambdaQueryWrapper.eq(StartSourceDataTable::getTableName, tableName);
        final StartSourceDataTable startSourceDataTable = startDataTableMapper.selectOne(lambdaQueryWrapper);
        if (startSourceDataTable != null) {
            return startSourceDataTable.getCrudOption();
        }
        if (!dbHasTable(dataSourcesKey, tableName)) {
            throw new StartBusException(String.format("数据源【%s】中未找到数据表【%s】", dataSourcesKey, tableName));
        }
        JSONObject option = new JSONObject();
        JSONArray column = new JSONArray();
        List<StartGenTableColumn> startGenTableColumns = startDataTableMapper.queryByTableColumn(dataSourcesKey, tableName).stream().collect(Collectors.toList());
        for (StartGenTableColumn col : startGenTableColumns) {
            col.createOption();
            column.add(col);
        }
        return option;
    }


}
